package codec

import (
	"bufio"
	"encoding/gob"
	"io"
	"log"
)

type GobCodec struct {
	// 由构建函数传入，通常是TCP或Unix建立Socket时得到的链接
	conn io.ReadWriteCloser
	// 防止阻塞而创建的带缓冲的Writer
	buf *bufio.Writer
	dec *gob.Decoder
	enc *gob.Encoder
}

// 检测GobCodec类型是否实现了Codec接口
var _ Codec = (*GobCodec)(nil)

func NewGobCodec(conn io.ReadWriteCloser) Codec{
	buf := bufio.NewWriter(conn)
	return &GobCodec{
		conn: conn,
		buf: buf,
		dec: gob.NewDecoder(conn),
		enc: gob.NewEncoder(buf),
	}
}

func (c *GobCodec) ReadHeader(h *Header) error {
	return c.dec.Decode(h)
}

func (c *GobCodec) Close() error {
	return c.conn.Close()
}

func (c *GobCodec) ReadBody(body interface{}) error {
	return c.dec.Decode(body)
}

func (c *GobCodec) Write(h *Header, body interface{}) (err error) {
	defer func() {
		_ = c.buf.Flush()
		if err != nil{
			_ = c.Close()
		}
	}()

	if err := c.enc.Encode(h); err != nil{
		log.Println("rpc codec: gob error encoding header: ", err)
		return err
	}

	if err := c.enc.Encode(body); err != nil{
		log.Println("rpc codec: gob error encoding body: ", err)
		return err
	}

	return nil
}